package com.example.core.aspect;

import com.example.core.annotation.CacheLock;
import com.example.core.common.CacheKeyGenerator;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

/**
 * @Author: 胡成
 * @Version: 0.0.1V
 * @Date: 2019/2/2
 * @Description: 类描述
 **/
@Aspect
@Configuration
public class LockMethodInterceptor {

    private final StringRedisTemplate stringRedisTemplate;
    private final CacheKeyGenerator cacheKeyGenerator;

    public LockMethodInterceptor(StringRedisTemplate stringRedisTemplate, CacheKeyGenerator cacheKeyGenerator) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.cacheKeyGenerator = cacheKeyGenerator;
    }

    @Around("execution(public * *(..)) && @annotation(com.example.core.annotation.CacheLock)")
    public Object interceptor(ProceedingJoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        CacheLock lock = method.getAnnotation(CacheLock.class);
        if (StringUtils.isEmpty(lock.prefix())) {
            throw new RuntimeException("lock key can't be null...");
        }

        final String lockKey = cacheKeyGenerator.getLockKey(pjp);

        try {

            final Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, "");
            if (success) {
                stringRedisTemplate.expire(lockKey, lock.expire(), lock.timeUnit());
            } else {
                //按理说，我们应该抛出一个自定义的CacheLockException 异常
                throw new RuntimeException("请勿重复请求");
            }

            try {
                return pjp.proceed();
            } catch (Throwable throwable) {
                throw new RuntimeException("系统异常");
            }
        } finally {
//            stringRedisTemplate.delete(lockKey);
        }

    }

}
